using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection.Emit;
using System.Text;
using System.Threading.Tasks;
using bitzhuwei.Compiler;
using static bitzhuwei.AnsiCFormat.Vndirect_declarator;

namespace bitzhuwei.AnsiCFormat {
    /// <summary>
    /// Correspond to the Vn node direct_declarator in the grammar(AnsiC).
    /// </summary>
    internal partial class Vndirect_declarator : IFullFormatter {
        // [131]=direct_declarator : 'identifier' ;
        // [132]=direct_declarator : '(' declarator ')' ;
        // [133]=direct_declarator : direct_declarator '[' constant_expression ']' ;
        // [134]=direct_declarator : direct_declarator '[' ']' ;
        // [135]=direct_declarator : direct_declarator '(' parameter_type_list ')' ;
        // [136]=direct_declarator : direct_declarator '(' identifier_list ')' ;
        // [137]=direct_declarator : direct_declarator '(' ')' ;

        public readonly Item first0;
        public readonly List<Item> list0 = new();

        private readonly TokenRange _scope;
        public TokenRange Scope => _scope;

        public void Format(TextWriter writer, FormatContext context) {
            throw new NotImplementedException();
        }

        public void FullFormat(BlankConfig preConfig, TextWriter writer, FormatContext context) {
            {
                context.PrintBlanksAnd(this.first0, preConfig, writer);
            }
            var first = true;
            var config = new BlankConfig(inlineBlank: 1, forceNewline: false);
            for (var i = 0; i < this.list0.Count; i++) {
                var item0 = this.list0[i];
                if (first) {
                    context.PrintCommentsBetween(this.first0, item0, config, writer);
                    first = false;
                }
                else {
                    context.PrintCommentsBetween(this.list0[i - 1], item0, config, writer);
                }
                context.PrintBlanksAnd(item0, config, writer);
            }
        }

        public IEnumerable<string> YieldTokens(TextWriter writer, FormatContext context) {
            throw new NotImplementedException();
        }
        /// <summary>
        /// [131]=direct_declarator : 'identifier' ;
        /// </summary>
        /// <param name="r0"></param>
        public Vndirect_declarator(Token r0) {
            this.first0 = new id_(r0);
            this._scope = new TokenRange(this.first0);
        }
        /// <summary>
        /// [132]=direct_declarator : '(' declarator ')' ;
        /// </summary>
        /// <param name="r2"></param>
        /// <param name="r1"></param>
        /// <param name="r0"></param>
        public Vndirect_declarator(Token r2, Vndeclarator r1, Token r0) {
            this.first0 = new declarator_(r2, r1, r0);
            this._scope = new TokenRange(this.first0);
        }

        /// <summary>
        /// [133]=direct_declarator : direct_declarator '[' constant_expression ']' ;
        /// [134]=direct_declarator : direct_declarator '[' ']' ;
        /// </summary>
        /// <param name="r2"></param>
        /// <param name="r1"></param>
        /// <param name="r0"></param>
        internal void Add(Token r2, Vnconstant_expression? r1, Token r0) {
            this.list0.Add(new const_(r2, r1, r0));
            this._scope.end = r0.end.index;
        }
        /// <summary>
        /// [135]=direct_declarator : direct_declarator '(' parameter_type_list ')' ;
        /// </summary>
        /// <param name="r2"></param>
        /// <param name="r1"></param>
        /// <param name="r0"></param>
        internal void Add(
            Token r2/* reserved word is omissible */
            , Vnparameter_type_list r1
            , Token r0/* reserved word is omissible */
        ) {
            this.list0.Add(new params_(r2, r1, r0));
            this._scope.end = r0.end.index;
        }
        /// <summary>
        /// [136]=direct_declarator : direct_declarator '(' identifier_list ')' ;
        /// </summary>
        /// <param name="r2"></param>
        /// <param name="r1"></param>
        /// <param name="r0"></param>
        internal void Add(
            Token r2/* reserved word is omissible */
            , Vnidentifier_list r1
            , Token r0/* reserved word is omissible */
        ) {
            this.list0.Add(new ids_(r2, r1, r0));
            this._scope.end = r0.end.index;
        }
        // dumped by ListExtractor 2
        /// <summary>
        /// [137]=direct_declarator : direct_declarator '(' ')' ;
        /// </summary>
        /// <param name="r1"></param>
        /// <param name="r0"></param>
        internal void Add(
            Token r1/* reserved word is omissible */
            , Token r0/* reserved word is omissible */
        ) {
            this.list0.Add(new empty_(r1, r0));
            this._scope.end = r0.end.index;
        }


        public abstract class Item : IFullFormatter {
            public abstract TokenRange Scope { get; }

            public abstract void Format(TextWriter writer, FormatContext context);
            public abstract void FullFormat(BlankConfig preConfig, TextWriter writer, FormatContext context);
            public abstract IEnumerable<string> YieldTokens(TextWriter writer, FormatContext context);
        }
        public class id_ : Item {
            private readonly Token identifier;

            public id_(Token r0) {
                this.identifier = r0;
                this._scope = new TokenRange(r0);
            }

            private readonly TokenRange _scope;
            public override TokenRange Scope => _scope;

            public override void Format(TextWriter writer, FormatContext context) {
                throw new NotImplementedException();
            }

            public override void FullFormat(BlankConfig preConfig, TextWriter writer, FormatContext context) {
                context.PrintBlanksAnd(this.identifier, preConfig, writer);
            }

            public override IEnumerable<string> YieldTokens(TextWriter writer, FormatContext context) {
                throw new NotImplementedException();
            }
        }
        public class declarator_ : Item {
            private readonly Token r2;
            private readonly Vndeclarator r1;
            private readonly Token r0;

            public declarator_(Token r2, Vndeclarator r1, Token r0) {
                this.r2 = r2;
                this.r1 = r1;
                this.r0 = r0;
                this._scope = new TokenRange(r2, r0);
            }

            private TokenRange _scope;
            public override TokenRange Scope => _scope;
            public override void Format(TextWriter writer, FormatContext context) {
                throw new NotImplementedException();
            }

            public override void FullFormat(BlankConfig preConfig, TextWriter writer, FormatContext context) {
                context.PrintBlanksAnd(this.r2, preConfig, writer);
                var config = new BlankConfig();
                context.PrintCommentsBetween(r2, r1, config, writer);
                context.PrintBlanksAnd(this.r1, config, writer);
                context.PrintCommentsBetween(r1, r0, config, writer);
                context.PrintBlanksAnd(this.r0, config, writer);
            }

            public override IEnumerable<string> YieldTokens(TextWriter writer, FormatContext context) {
                throw new NotImplementedException();
            }
        }
        public class const_ : Item {
            private readonly Token r2;
            private readonly Vnconstant_expression? r1;
            private readonly Token r0;

            public const_(Token r2, Vnconstant_expression? r1, Token r0) {
                this.r2 = r2;
                this.r1 = r1;
                this.r0 = r0;
                this._scope = new TokenRange(r2, r0);
            }

            private TokenRange _scope;
            public override TokenRange Scope => _scope;
            public override void Format(TextWriter writer, FormatContext context) {
                throw new NotImplementedException();
            }

            public override void FullFormat(BlankConfig preConfig, TextWriter writer, FormatContext context) {
                context.PrintBlanksAnd(this.r2, preConfig, writer);
                var config = new BlankConfig();
                if (r1 != null) {
                    context.PrintCommentsBetween(r2, r1, config, writer);
                    context.PrintBlanksAnd(this.r1, config, writer);
                    context.PrintCommentsBetween(r1, r0, config, writer);
                }
                else {
                    context.PrintCommentsBetween(r2, r0, config, writer);
                }
                context.PrintBlanksAnd(r0, config, writer);
            }

            public override IEnumerable<string> YieldTokens(TextWriter writer, FormatContext context) {
                throw new NotImplementedException();
            }
        }
        public class params_ : Item {
            private readonly Token r2;
            private readonly Vnparameter_type_list r1;
            private readonly Token r0;

            public params_(Token r2, Vnparameter_type_list r1, Token r0) {
                this.r2 = r2;
                this.r1 = r1;
                this.r0 = r0;
                this._scope = new TokenRange(r2, r0);
            }

            private TokenRange _scope;
            public override TokenRange Scope => _scope;
            public override void Format(TextWriter writer, FormatContext context) {
                throw new NotImplementedException();
            }

            public override void FullFormat(BlankConfig preConfig, TextWriter writer, FormatContext context) {
                context.PrintBlanksAnd(this.r2, preConfig, writer);
                var config = new BlankConfig();
                context.PrintCommentsBetween(r2, r1, config, writer);
                context.PrintBlanksAnd(this.r1, config, writer);
                context.PrintCommentsBetween(r1, r0, config, writer);
                context.PrintBlanksAnd(this.r0, config, writer);
            }

            public override IEnumerable<string> YieldTokens(TextWriter writer, FormatContext context) {
                throw new NotImplementedException();
            }
        }
        public class ids_ : Item {
            private readonly Token r2;
            private readonly Vnidentifier_list r1;
            private readonly Token r0;

            public ids_(Token r2, Vnidentifier_list r1, Token r0) {
                this.r2 = r2;
                this.r1 = r1;
                this.r0 = r0;
                this._scope = new TokenRange(r2, r0);
            }

            private TokenRange _scope;
            public override TokenRange Scope => _scope;

            public override void Format(TextWriter writer, FormatContext context) {
                throw new NotImplementedException();
            }

            public override void FullFormat(BlankConfig preConfig, TextWriter writer, FormatContext context) {
                context.PrintBlanksAnd(this.r2, preConfig, writer);
                var config = new BlankConfig();
                context.PrintCommentsBetween(r2, r1, config, writer);
                context.PrintBlanksAnd(this.r1, config, writer);
                context.PrintCommentsBetween(r1, r0, config, writer);
                context.PrintBlanksAnd(this.r0, config, writer);
            }

            public override IEnumerable<string> YieldTokens(TextWriter writer, FormatContext context) {
                throw new NotImplementedException();
            }
        }
        public class empty_ : Item {
            private readonly Token r1;
            private readonly Token r0;

            public empty_(Token r1, Token r0) {
                this.r1 = r1;
                this.r0 = r0;
                this._scope = new TokenRange(r1, r0);
            }

            private TokenRange _scope;
            public override TokenRange Scope => _scope;

            public override void Format(TextWriter writer, FormatContext context) {
                throw new NotImplementedException();
            }

            public override void FullFormat(BlankConfig preConfig, TextWriter writer, FormatContext context) {
                context.PrintBlanksAnd(this.r1, preConfig, writer);
                var config = new BlankConfig();
                context.PrintCommentsBetween(r1, r0, config, writer);
                context.PrintBlanksAnd(this.r0, config, writer);
            }

            public override IEnumerable<string> YieldTokens(TextWriter writer, FormatContext context) {
                throw new NotImplementedException();
            }
        }


    }
}
